package com.myMinistry.gui;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.view.KeyEvent;
import android.widget.ArrayAdapter;

import com.myMinistry.R;
import com.myMinistry.provider.MinistryContract.EntryType;
import com.myMinistry.provider.MinistryContract.Rollover;
import com.myMinistry.provider.MinistryContract.Time;
import com.myMinistry.provider.MinistryService;

public class TimeEntries extends FragmentActivity {
	private final Calendar date = Calendar.getInstance();
	private MinistryService database;
	private SharedPreferences sharedPref;
	
	@Override
	public void onStop() {
		super.onStop();
    }
	
	@Override
	public void onStart() {
		super.onStart();
		updateList(sharedPref.getInt(Summary.MY_PREFS_KEY_PUBLISHER_ID, 0));
    }
    
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
    		Intent intent = new Intent(getApplicationContext(), Summary.class);
			intent.putExtra("month", date.get(Calendar.MONTH));
			intent.putExtra("year", date.get(Calendar.YEAR));
			startActivity(intent);
			finish();
        }
        return super.onKeyDown(keyCode, event);
    }
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
    	setContentView(R.layout.time_entries);
    	Bundle extras = getIntent().getExtras();
    	sharedPref = getSharedPreferences(Summary.MY_PREFS, Context.MODE_PRIVATE);
    	
    	if(extras != null) {
			Object[] keys = extras.keySet().toArray();
			for(int i = 0; i < keys.length; i++) {
				if(keys[i].toString().equals("year"))
					date.set(Calendar.YEAR, extras.getInt("year"));
				else if(keys[i].toString().equals("month"))
					date.set(Calendar.MONTH, extras.getInt("month"));
			}
		}
    }
	
	public void updatePublisher(int newPublisherID, String publisherName) {
		/** Update display name from fragment */
		ActionBarFragment fragment = (ActionBarFragment)getSupportFragmentManager().findFragmentById(R.id.action_bar_fragment);
		fragment.setSelectedPublisherNameText(publisherName);
		
		/** Update local variable and update the summary info */
		updateList(newPublisherID);
	}
	
	public void showDialog() {
		/** DialogFragment.show() will take care of adding the fragment
		 * in a transaction. We also want to remove any currently showing
		 * dialogs, so make our own transaction and take care of that here. */
		FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
		Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
		if(prev != null)
			ft.remove(prev);
		ft.addToBackStack(null);
		/** Create and show the dialog. */
		DialogFrag newFragment = DialogFrag.newInstance(getApplicationContext().getString(R.string.menuPublishers), DialogFrag.ACTIVE_PUBLISHERS);
		newFragment.show(getSupportFragmentManager(), "dialog");
	}
	
	public void createNewPublisherShowDialog() {
		/** DialogFragment.show() will take care of adding the fragment
		 * in a transaction. We also want to remove any currently showing
		 * dialogs, so make our own transaction and take care of that here. */
		FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
		Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
		if(prev != null)
			ft.remove(prev);
		ft.addToBackStack(null);
		/** Create and show the dialog. */
		DialogFrag newFragment = DialogFrag.newInstance(getApplicationContext().getString(R.string.publishersName), DialogFrag.CREATE_PUBLISHER);
		newFragment.show(getSupportFragmentManager(), "dialog");
	}
	
	public void updateList(int _publisherID) {
		/** Update display name from fragment */
		TimeEntriesListFrag fragment = (TimeEntriesListFrag)getSupportFragmentManager().findFragmentById(R.id.time_entries_list_fragment);
		fragment.updateList(_publisherID, date);
	}
	
	public void removeEntry(int id) {
		/** do not allow deletion of roll over... */
		database = new MinistryService(this);
		database.openWritable();
		database.deleteTimeByID(id);
		database.close();
		processRolloverTime(sharedPref.getInt(Summary.MY_PREFS_KEY_PUBLISHER_ID, 0), date);
		/** Update the list from the fragment. */
		TimeEntriesListFrag fragment = (TimeEntriesListFrag)getSupportFragmentManager().findFragmentById(R.id.time_entries_list_fragment);
		fragment.removeEntry();
	}
	
	public void editEntry(int _publisherID) {
		/** Update display name from fragment */
		TimeEntriesListFrag fragment = (TimeEntriesListFrag)getSupportFragmentManager().findFragmentById(R.id.time_entries_list_fragment);
		fragment.updateList(_publisherID, date);
	}
	
	public void itemTouched(int selectedID) {
		showDialog(selectedID);
	}
    
    @Override
	protected Dialog onCreateDialog(final int id) {
    	Dialog dialog = null;
    	AlertDialog.Builder builder = new Builder(this);
    	builder.setTitle(R.string.editEntry);
    	ArrayList<String> list = new ArrayList<String>();
    	list.add(getApplicationContext().getString(R.string.removeTimeEntry));
    	list.add(getApplicationContext().getString(R.string.editTimeEntry));
		
    	ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.simple_list_item_1, R.id.text1, list);
    	
    	builder.setInverseBackgroundForced(true);
    	builder.setAdapter(adapter, new OnClickListener() {
    		@Override
    		public void onClick(DialogInterface dialog, int which) {
    			/** They want to delete the entry */
    			if(which == 0)
    				removeEntry(id);
    			/** They want to edit the entry */
    			else if(which == 1) {
    				Intent intent = new Intent(getApplicationContext(), TimeEditor.class);
    				intent.putExtra("timeID", id);
    				startActivity(intent);
    				finish();
    			}
    		}});
    	builder.create();
    	dialog = builder.show();
    	return dialog;
    }
    
    private void processRolloverTime(int _publisherID, Calendar _startDate) {
    	SimpleDateFormat saveDateFormat	= new SimpleDateFormat("yyyy-MM-dd");
    	Calendar roDate = _startDate;
    	Calendar stopDate = Calendar.getInstance();
    	double sum = 0;
    	double currentMinutes = 0;
    	double previousMinutes = 0;
    	int rolloverTimeID = 0;
    	int rolloverID = 0;
    	ContentValues timeValues = new ContentValues();
    	ContentValues roValues = new ContentValues();
    	
    	/** Default the day to the first and the time zero'd out */
    	roDate.set(Calendar.DAY_OF_MONTH, 1);
    	roDate.set(Calendar.HOUR, 0);
    	roDate.set(Calendar.MINUTE, 0);
    	roDate.set(Calendar.SECOND, 0);
    	roDate.set(Calendar.MILLISECOND, 0);
    	stopDate.set(Calendar.DAY_OF_MONTH, 1);
    	stopDate.set(Calendar.HOUR, 0);
    	stopDate.set(Calendar.MINUTE, 0);
    	stopDate.set(Calendar.SECOND, 0);
    	stopDate.set(Calendar.MILLISECOND, 0);
    	
    	/** Default ContentValues for a time and roll over entry */
    	timeValues.put(Time.PUBLISHER_ID, _publisherID);
    	timeValues.put(Time.HOUSEHOLDER_ID, 0);
    	timeValues.put(Time.ENTRY_TYPE_ID, EntryType.ROLLOVER_ID);
    	timeValues.put(Time.TOTAL_HOURS, 1);
    	timeValues.put(Time.RETURN_VISITS, 0);
    	/** Will be replaced during the loop */
    	timeValues.put(Time.DATE, "");
    	/** Midnight */
    	timeValues.put(Time.TIME_START, "00:00");
    	/** 1 AM */
    	timeValues.put(Time.TIME_END, "01:00");
    	
    	roValues.put(Rollover.PUBLISHER_ID, _publisherID);
    	/** Will be replaced during the loop */
    	roValues.put(Rollover.DATE, "");
    	/** Will be replaced during the loop */
    	roValues.put(Rollover.MINUTES, 0);
    	
    	/** Prepare for the while loop by getting the previous month's minutes if they exist. */
    	roDate.add(Calendar.MONTH, -1);
    	database.openWritable();
    	Cursor record = database.fetchRolloverMinutes(_publisherID, saveDateFormat.format(roDate.getTime()));
    	if(record.moveToFirst())
    		previousMinutes = record.getDouble(record.getColumnIndex(Rollover.MINUTES));
    	record.close();
    	/** Add the month back that we took away to get the previous months minutes */
    	roDate.add(Calendar.MONTH, 1);
    	
    	/** Compare values
		 *  0 if the times of the two Calendars are equal
		 *  -1 if the time of this Calendar is before the other one
		 *  1 if the time of this Calendar is after the other one
		 */
    	/** This loop will run while the date is less than or equal to now() */
    	while (roDate.compareTo(stopDate) != 1) {
    		/** Reset the ID's */
    		rolloverTimeID = 0;
    		rolloverID = 0;
    		sum = 0;
    		
    		/** Save the dates */
    		timeValues.put(Time.DATE,saveDateFormat.format(roDate.getTime()));
    		roValues.put(Rollover.DATE,saveDateFormat.format(roDate.getTime()));
    		
    		/** Is there already a rollover time entry for this month? If so we need that time entry _id */
			record = database.fetchRolloverTimeEntry(saveDateFormat.format(roDate.getTime()), _publisherID);
			if(record.moveToFirst())
				rolloverTimeID = record.getInt(record.getColumnIndex(Time._ID));
			record.close();
			
			/** Is there already a roll over entry for this month? If so we need that rollover entry _id */
			record = database.fetchRolloverMinutes(_publisherID, saveDateFormat.format(roDate.getTime()));
			if(record.moveToFirst())
				rolloverID = record.getInt(record.getColumnIndex(Rollover._ID));
			record.close();
			
			/** Get month's hours */
			sum = database.fetchHoursForMonthForPublisher(saveDateFormat.format(roDate.getTime()), _publisherID);
			currentMinutes = sum - (int) sum;
			
			/** If the minutes add up to be over an hour we need to create/update the roll over time entry */
			if(currentMinutes + previousMinutes >= 1) {
				/** Update record */
				if(rolloverTimeID != 0)
					database.updateTimeEntry(rolloverTimeID, timeValues);
				/** Create record */
				else
					database.createTimeEntry(timeValues);
				/** Save the remainder of minutes. */
				previousMinutes += currentMinutes - 1;
			}
			
			/** We need to delete the time entry if it exists */
			else if(rolloverTimeID != 0) {
				database.removeTimeEntry(rolloverTimeID);
				previousMinutes += currentMinutes;
			}
			else
				previousMinutes += currentMinutes;
			
			roValues.put(Rollover.MINUTES, previousMinutes);
			
			/** Update record */
			if(rolloverID != 0)
				database.updateRolloverMinutes(rolloverID, roValues);
			/** Create record */
			else
				database.createRolloverMinutes(roValues);
    		
    		/** Increase the date by a month */
    		roDate.add(Calendar.MONTH, 1);
    	}
    	database.close();
    }
}